home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / Appearance SDK 1.0.4 / Appearance Sample Code / Source / AppearanceSampleMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-16  |  28.0 KB  |  1,107 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        AppearanceSampleMain.c
  3.  
  4.     Contains:    Main application code for our sample app.
  5.  
  6.     Version:    Appearance 1.0.2 SDK
  7.  
  8.     Copyright:    © 1997-98 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                Edward Voas
  13.  
  14.         Other Contact:        7 of 9, Borg Collective
  15.  
  16.         Technology:            OS Technologies Group
  17.  
  18.     Writers:
  19.  
  20.         (MAA)    Matt Ackeret
  21.         (edv)    Ed Voas
  22.  
  23.     Change History (most recent first):
  24.          <5>     1/23/98    mxm        Added AutoSizeDialog for the About box
  25.          <4>    10/29/97    MAA        Put the font menu into a global so we can disable it when
  26.                                     CDEFTester goes away.
  27.          <3>    10/28/97    MAA        Add Font menu back in, fix a bug in SetUpFontMenu
  28.          <2>    10/28/97    edv        Use RadioGroup control!
  29.          <1>     9/11/97    edv        First checked in.
  30. */
  31.  
  32.  
  33. //
  34. //    This program is actually based on the skeleton code from Scott Knaster's
  35. //    Macintosh Programming Secrets book. So, if you're looking at this code,
  36. //    Scott, it may look slightly familiar.
  37. //
  38.  
  39. #include <Types.h>
  40. #include <Files.h>
  41. #include <Gestalt.h>
  42. #include <Processes.h>
  43. #include <Movies.h>
  44. #include <Menus.h>
  45. #include <Fonts.h>
  46. #include <DiskInit.h>
  47. #include <Devices.h>
  48. #include <TextUtils.h>
  49. #include <Resources.h>
  50. #include "Traps.h"
  51. #include "TrapTools.h"
  52. #include "Appearance.h"
  53.  
  54. #include "FinderWindow.h"
  55. #include "DialogWindow.h"
  56. #include "BevelDialog.h"
  57. #include "BevelImageAPIWindow.h"
  58. #include "CDEFTester.h"
  59. #include "LiveFeedbackDialog.h"
  60. #include "MegaDialog.h"
  61. #include "UtilityWindow.h"
  62. #include "SideUtilityWindow.h"
  63. #include "MenuDrawing.h"
  64.  
  65. #define    MAXLONG        0X7FFFFFFF
  66.  
  67. /* ==================================================================================*/
  68. /* ======================= R E S O U R C E   N U M B E R S ==========================*/
  69. /* ==================================================================================*/
  70.  
  71. enum
  72. {
  73.     kAlertStartupError        = 129
  74. };
  75.  
  76. enum
  77. {
  78.     kErrorStrings            = 128,
  79.     kWeirdSystemString        = 1,
  80.     kNoAppearanceString        = 2,
  81.     kResourceMissingString    = 3
  82. };
  83.  
  84. enum
  85. {
  86.     kAboutBoxDialogID        = 5000
  87. };
  88.  
  89. #define kObjectWindowKind        2000
  90.  
  91. /*     The following constants are used to identify menus and their items. The menu IDs
  92.     have an "m" prefix and the item numbers within each menu have an "i" prefix. */
  93.  
  94. enum
  95. {
  96.     rMenuBar                = 128                /* application's menu bar */
  97. };
  98.  
  99. enum
  100. {
  101.     mApple                    = 128,                /* Apple menu */
  102.     iAbout                    = 1
  103. };
  104.  
  105. enum
  106. {
  107.     mFile                    = 129,                /* File menu */
  108.     iClose                    = 1,
  109.     iQuit                    = 3
  110. };
  111.  
  112. enum
  113. {
  114.     kHorizZoomKind            = 128,
  115.     kVertZoomKind            = 129
  116. };
  117.  
  118. enum
  119. {
  120.     kMenuModifiers                = 145,
  121.     kNoModifiersItem            = 1,
  122.     kShiftModifierItem            = 2,
  123.     kShiftOptionModifierItem    = 3,
  124.     kShiftOptCntlModifierItem    = 4,
  125.     kCommandDeleteItem            = 5,
  126.     kIconSuiteItem                = 6
  127. };
  128.  
  129. enum
  130. {
  131.     kAboutSampleCmd            = 'abou',
  132.     kCloseCmd                = 'clos',
  133.     kQuitCmd                = 'quit',
  134.     kOpenFinderWindowCmd    = 'opfw',
  135.     kOpenDialogWindowCmd    = 'opdw',
  136.     kOpenBevelDialogCmd        = 'opbd',
  137.     kNewFeaturesDialogCmd    = 'newf',
  138.     kStandardAlertCmd        = 'stal',
  139.     kBevelImageAPICmd        = 'bvli',
  140.     kCDEFTesterCmd            = 'cdef',
  141.     kLiveFeedbackCmd        = 'live',
  142.     kUtilityWindowCmd        = 'util',
  143.     kSideUtilityWindowCmd    = 'side',
  144.     kMegaDialogCmd            = 'mega',
  145.     kAutoSizeCmd            = 'asiz',
  146.     kVerticalZoomCmd        = 'vert',
  147.     kHorizontalZoomCmd        = 'horz'
  148. };
  149.  
  150. enum
  151. {
  152.     kMenuDrawingTest        = 'mdra',
  153.     kDumpHierarchy            = 'dhie'
  154. };
  155.  
  156. //——————————————————————————————————————————————————————————————————————————————————
  157. //    Prototypes
  158. //——————————————————————————————————————————————————————————————————————————————————
  159.  
  160. static void        InitToolbox(void);
  161. static void        MainEventLoop(void);
  162.  
  163. /* Event handling routines */
  164.  
  165. static void        HandleEvent(EventRecord *event);
  166. static void        HandleActivate(EventRecord *event);
  167. static void        HandleDiskInsert(EventRecord *event);
  168. static void        HandleKeyPress(EventRecord *event);
  169. static void     HandleMouseDown(EventRecord *event);
  170. static void        HandleOSEvent(EventRecord *event);
  171. static void        HandleUpdate(EventRecord *event);
  172.  
  173. static void        AdjustMenus(void);
  174. static void        HandleMenuCommand(long menuResult);
  175.  
  176. /* Utility routines */
  177.  
  178. static void        CloseAnyWindow(WindowPtr window);
  179. static void        DeathAlert(short errorNumber);
  180. static Boolean    IsAppWindow(WindowPtr window);
  181. static Boolean     IsDAWindow(WindowPtr window);
  182. static Boolean    IsDialogWindow(WindowPtr window);
  183.  
  184. static Boolean    GetObjectFromWindow( WindowPtr window, BaseWindow** wind );
  185. static void        SetUpFontMenu();
  186. static void        SetUpModifiersMenu();
  187. static void        DoAboutBox();
  188.  
  189. static void        AutoSizeDialogTest();
  190. static void        SyncVertZoomRects( WindowPtr window );
  191. static void        SyncHorizZoomRects( WindowPtr window );
  192. static OSErr    GetReportFileSpec( FSSpecPtr file );
  193.  
  194. /* External routines */
  195.  
  196. extern void        TestStandardAlert();
  197.  
  198. //———————————————————————————————————————————————————————————————————————————
  199. //    Globals
  200. //———————————————————————————————————————————————————————————————————————————
  201.  
  202.  
  203. Boolean            gQuit;            /*     We set this to TRUE when the user selects
  204.                                     Quit from the File menu. Our main event loop
  205.                                     exits gQuit is TRUE. */
  206.  
  207. Boolean            gInBackground;    /*    gInBackground is maintained by our osEvent
  208.                                     handling routines. Any poart of the program
  209.                                     can check it to find out if it is currently
  210.                                     in the background. */
  211.  
  212. MenuHandle        gFontMenu = nil;        // Menu used to choose a font
  213.  
  214. //———————————————————————————————————————————————————————————————————————————
  215. //    Macros
  216. //———————————————————————————————————————————————————————————————————————————
  217.  
  218. #define    HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  219. #define    LoWrd(aLong)    ((aLong) & 0xFFFF)
  220.  
  221. //———————————————————————————————————————————————————————————————————————————
  222. //    • main
  223. //———————————————————————————————————————————————————————————————————————————
  224. //    Entry point for our program. We initialize the Toolbox, make sure we are
  225. //    running on a sufficiently brawny machine, and put up the menu bar. Finally,
  226. //    we start polling for events and handling then by entering our main event
  227. //    loop.
  228. //    
  229. void main()
  230. {
  231.     /*    If you have stack requirements that differ from the default,
  232.         then you could use SetApplLimit to increase StackSpace at
  233.         this point, before calling MaxApplZone. */
  234.         
  235.     MaxApplZone();                        /*     Expand the heap so code segments load
  236.                                             at the top */
  237.     InitToolbox();                        /*    Initialize the program */
  238.     MainEventLoop();                    /*     Call the main event loop */
  239. }
  240.  
  241. //———————————————————————————————————————————————————————————————————————————
  242. //    • InitToolbox
  243. //———————————————————————————————————————————————————————————————————————————
  244. //    Set up the whole world, including global variables, Toolbox Managers, and
  245. //    menus.
  246. //    
  247. static void
  248. InitToolbox()
  249. {
  250.     Handle            menuBar;
  251.     SInt32            result;
  252.     OSErr            err;
  253.     
  254.     gInBackground = false;
  255.     gQuit = false;
  256.     
  257.     InitGraf((Ptr) &qd.thePort);
  258.     InitFonts();
  259.     InitWindows();
  260.     InitMenus();
  261.     TEInit();
  262.     InitDialogs(nil);
  263.     InitCursor();
  264.     
  265.     if ( !TrapAvailable( _WaitNextEvent ) )
  266.         DeathAlert( kWeirdSystemString );
  267.     
  268.     err = Gestalt( gestaltAppearanceAttr, &result );
  269.     if ( err )
  270.         DeathAlert( kNoAppearanceString );
  271.         
  272.     menuBar = GetNewMBar(rMenuBar);
  273.     if ( menuBar == nil )
  274.         DeathAlert( kResourceMissingString );
  275.     
  276.         //**************************************************************************//
  277.         //    APPEARANCE ADOPTION ALERT!!                                                //
  278.         //**************************************************************************//
  279.  
  280.         // In order to get the theme-savvy menu bar, we need to call
  281.         // RegisterAppearanceClient.
  282.  
  283.     RegisterAppearanceClient();
  284.  
  285.     SetMenuBar(menuBar);
  286.     
  287.     DisposeHandle(menuBar);
  288.     AppendResMenu(GetMenuHandle(mApple),'DRVR');
  289.     
  290.     SetUpFontMenu();
  291.  
  292.     SetUpModifiersMenu();
  293.     
  294.     AdjustMenus();
  295.  
  296.     DrawMenuBar();
  297.         
  298.     new MegaDialog();
  299. }
  300.  
  301. //———————————————————————————————————————————————————————————————————————————
  302. //    • MainEventLoop
  303. //———————————————————————————————————————————————————————————————————————————
  304. //    Get events and handle them by calling HandleEvent. On every event, we call
  305. //    idle on the frontmost window, if there is one.
  306. //    
  307. static void
  308. MainEventLoop()
  309. {
  310.     RgnHandle        cursorRgn;
  311.     Boolean            gotEvent;
  312.     EventRecord        event;
  313.     WindowPtr        theWindow;
  314.     BaseWindow*        window;
  315.     
  316.     cursorRgn = nil;
  317.     while( !gQuit )
  318.     {
  319.         gotEvent = WaitNextEvent( everyEvent, &event, MAXLONG, cursorRgn );
  320.         if ( gotEvent )
  321.             HandleEvent( &event );
  322.         
  323.         theWindow = FrontWindow();
  324.         if ( theWindow && GetObjectFromWindow( theWindow, &window ) )
  325.         {
  326.             window->Idle();            
  327.         }
  328.     }
  329. }
  330.  
  331. //———————————————————————————————————————————————————————————————————————————
  332. //    • HandleEvent
  333. //———————————————————————————————————————————————————————————————————————————
  334. //    Do the right thing for an event. Determine what kind of event it is and
  335. //    call the appropriate routines.
  336. //
  337. static void
  338. HandleEvent( EventRecord *event )
  339. {
  340.     switch ( event->what )
  341.     {
  342.         case mouseDown:
  343.             HandleMouseDown( event );
  344.             break;
  345.             
  346.         case keyDown:
  347.         case autoKey:
  348.             HandleKeyPress( event );
  349.             break;
  350.             
  351.         case activateEvt:
  352.             HandleActivate( event );
  353.             break;
  354.             
  355.         case updateEvt:
  356.             HandleUpdate( event );
  357.             break;
  358.             
  359.         case diskEvt:
  360.             HandleDiskInsert( event );
  361.             break;
  362.             
  363.         case osEvt:
  364.             HandleOSEvent( event );
  365.     }
  366. }
  367.  
  368. //———————————————————————————————————————————————————————————————————————————
  369. //    • HandleActivate
  370. //———————————————————————————————————————————————————————————————————————————
  371. //    This is called when a window is activated or deactivated. In this sample,
  372. //    the Window Manager's handling of activate and deactivate events is
  373. //    sufficient. Others applications may have TextEdit records, controls, lists,
  374. //    etc., to activate/deactivate.
  375. //
  376. static void
  377. HandleActivate( EventRecord *event )
  378. {
  379.     WindowPtr        theWindow;
  380.     Boolean            becomingActive;
  381.     BaseWindow*        windObj;
  382.     
  383.     theWindow = (WindowPtr)event->message;
  384.     becomingActive = (event->modifiers & activeFlag) != 0;
  385.  
  386.     if ( IsDialogWindow( theWindow ) )
  387.     {
  388.         DialogRef        dialog;
  389.         SInt16            itemHit;
  390.  
  391.         DialogSelect( event, &dialog, &itemHit );
  392.     }
  393.     else if ( GetObjectFromWindow( theWindow, &windObj ) )
  394.     {
  395.         if ( becomingActive )
  396.             windObj->Activate( *event );
  397.         else
  398.             windObj->Deactivate( *event );
  399.     }
  400. }
  401.  
  402. //———————————————————————————————————————————————————————————————————————————
  403. //    • HandleDiskInsert
  404. //———————————————————————————————————————————————————————————————————————————
  405. //    Called when we get a disk-inserted event. Check the upper word of the
  406. //    event message; if it's nonzero, then a bad disk was inserted, and it
  407. //    needs to be formatted.
  408. //    
  409. static void
  410. HandleDiskInsert( EventRecord *event )
  411. {
  412.     Point        aPoint = {100, 100};
  413.     
  414.     if ( HiWrd( event->message ) != noErr )
  415.     {
  416.         DIBadMount( aPoint, event->message );
  417.     }
  418. }
  419.  
  420. //———————————————————————————————————————————————————————————————————————————
  421. //    • HandleKeyPress
  422. //———————————————————————————————————————————————————————————————————————————
  423. //    The user pressed a key, what are you going to do about it?
  424. //
  425. static void
  426. HandleKeyPress( EventRecord *event )
  427. {
  428.     char        key;
  429.     
  430.     key = event->message & charCodeMask;
  431.     if ( event->modifiers & cmdKey )
  432.     {
  433.         AdjustMenus();
  434.  
  435.         //**************************************************************************//
  436.         //    APPEARANCE ADOPTION ALERT!!                                                //
  437.         //**************************************************************************//
  438.         // Here we use the new MenuEvent routine instead of menu key. This allows
  439.         // us to handle extended modifier keys for the menu items that use them.
  440.         
  441.         HandleMenuCommand( MenuEvent( event ) );
  442.     }
  443.     else
  444.     {
  445.         WindowPtr     window = FrontWindow();
  446.         BaseWindow*    object;
  447.         
  448.         if ( GetObjectFromWindow( window, &object ) )
  449.         {
  450.             object->HandleKeyDown( *event );
  451.         }
  452.     }
  453. }
  454.  
  455. //———————————————————————————————————————————————————————————————————————————
  456. //    • HandleMouseDown
  457. //———————————————————————————————————————————————————————————————————————————
  458. //    Called to handle mouse clicks. The user could have clicked anywhere,so
  459. //    let's first find out where by calling FindWindow. That returns a number
  460. //    indicating where in the screen the mouse was clicked. "switch" on that
  461. //    number and call the appropriate routine.
  462. //
  463. static void
  464. HandleMouseDown( EventRecord *event )
  465. {
  466.     long        newSize;
  467.     Rect        growRect;
  468.     WindowPtr    theWindow;
  469.     short        part;
  470.     
  471.     part = FindWindow( event->where, &theWindow );
  472.     
  473.     switch ( part )
  474.     {
  475.         case inMenuBar:
  476.             AdjustMenus();
  477.             HandleMenuCommand( MenuSelect( event->where ) );
  478.             break;
  479.             
  480.         case inSysWindow:
  481.             SystemClick( event, theWindow );
  482.             break;
  483.             
  484.         case inContent:
  485.             if ( theWindow != FrontWindow() )
  486.             {
  487.                 SelectWindow( theWindow );
  488.             }
  489.             else
  490.             {
  491.                 BaseWindow*     wind;
  492.                 
  493.                 if ( GetObjectFromWindow( theWindow, &wind ) )
  494.                     wind->HandleClick( *event );
  495.             }
  496.             break;
  497.             
  498.         case inDrag:
  499.             DragWindow( theWindow, event->where, &qd.screenBits.bounds );
  500.             if ( ((WindowPeek)theWindow)->windowKind == kHorizZoomKind )
  501.                 SyncHorizZoomRects( theWindow );
  502.             else if ( ((WindowPeek)theWindow)->windowKind == kVertZoomKind )
  503.                 SyncVertZoomRects( theWindow );
  504.             break;
  505.             
  506.         case inGrow:
  507.             growRect = qd.screenBits.bounds;
  508.             growRect.top = growRect.left = 80;
  509.             newSize = GrowWindow(theWindow,event->where,&growRect);
  510.             if (newSize != 0)
  511.             {
  512.                 BaseWindow*        wind;
  513.                 
  514.                 if ( GetObjectFromWindow( theWindow, &wind ) )
  515.                     wind->Resize( LoWrd(newSize), HiWrd(newSize) );
  516.                 else
  517.                     SizeWindow( theWindow, LoWrd( newSize ), HiWrd( newSize ), true );
  518.             }
  519.             break;
  520.             
  521.         case inGoAway:
  522.             if (TrackGoAway(theWindow,event->where))
  523.                 CloseAnyWindow(theWindow);
  524.             break;
  525.             
  526.         case inZoomIn:
  527.         case inZoomOut:
  528.             if ( TrackBox( theWindow, event->where, part ) )
  529.             {
  530.                 SetPort( theWindow );
  531.                 EraseRect( &theWindow->portRect );
  532.                 ZoomWindow( theWindow, part, true );
  533.                 InvalRect( &theWindow->portRect );
  534.             }
  535.             break;
  536.     }
  537. }
  538.  
  539. //———————————————————————————————————————————————————————————————————————————
  540. //    • HandleOSEvent
  541. //———————————————————————————————————————————————————————————————————————————
  542. //    Deal with OSEvents. These are messages that the process manager sends to
  543. //    us. Here, we deal with the suspend and resume message.
  544. //    
  545. static void
  546. HandleOSEvent( EventRecord *event )
  547. {
  548.     switch( (event->message >> 24) & 0x00FF )
  549.     {
  550.         case suspendResumeMessage:
  551.         
  552.                 // In our SIZE resource, we say that we are MultiFinder aware.
  553.                 // This means that we take on the responsibility of activating
  554.                 // and deactivating our own windows on suspend/resume events. */
  555.  
  556.             gInBackground = (event->message & resumeFlag) == 0;
  557.  
  558.             WindowPtr        window = FrontWindow();
  559.         
  560.             if ( window )
  561.             {
  562.                 BaseWindow*        wind;
  563.                 
  564.                 if ( GetObjectFromWindow( window, &wind ) )
  565.                 {
  566.                     if ( gInBackground )
  567.                         wind->Deactivate( *event );
  568.                     else
  569.                         wind->Activate( *event );
  570.                 }
  571.             }
  572.             break;
  573.             
  574.         case mouseMovedMessage:
  575.             break;
  576.     }
  577. }
  578.  
  579. //———————————————————————————————————————————————————————————————————————————
  580. //    • HandleUpdate
  581. //———————————————————————————————————————————————————————————————————————————
  582. //    This is called when an update event is received for a window. It calls
  583. //    DoUpdateWindow to draw the contents of an application window. As an
  584. //    efficiency measure that does not have to be followed, it calls the drawing
  585. //    routine only if the visRgn is nonempty. This will handle situations where
  586. //    calculations for drawing or drawing itself is very time consuming.
  587. //    
  588. static void
  589. HandleUpdate( EventRecord *event )
  590. {
  591.      WindowPtr            theWindow = (WindowPtr)event->message;
  592.      BaseWindow*        wind;
  593.      
  594.     if ( IsDialogWindow( theWindow ) )
  595.     {
  596.         DialogRef        dialog;
  597.         SInt16            itemHit;
  598.  
  599.         DialogSelect( event, &dialog, &itemHit );
  600.     }
  601.     else if ( GetObjectFromWindow( theWindow, &wind ) )
  602.     {
  603.          if ( !EmptyRgn( theWindow->visRgn ) )
  604.          {
  605.              SetPort( theWindow );
  606.              wind->Update( *event );
  607.          }
  608.     }
  609.     else
  610.     {
  611.         BeginUpdate( theWindow );
  612.         EndUpdate( theWindow );
  613.     }
  614. }
  615.  
  616. //———————————————————————————————————————————————————————————————————————————
  617. //    • AdjustMenus
  618. //———————————————————————————————————————————————————————————————————————————
  619. //    Enable and disable menus based on the currene state. The user can only 
  620. //    select enabled menu items. We set up all the menu items before calling
  621. //    MenuSelect or MenuKey, since these are the only times that a menu item can
  622. //    be selected. Note that MenuSelect is also the only time the user will see
  623. //    menu items. This approach to deciding what enable/disable state a menu
  624. //    item has has the advantage of concentrating all the decision making in one
  625. //    routine, as opposed to being spread throughout the application. Other
  626. //    application designs may take a different approach that is just as valid.
  627. //    
  628. static void
  629. AdjustMenus()
  630. {
  631.     WindowPtr        theWindow;
  632.     MenuHandle        menu;
  633.     BaseWindow*        wind;
  634.     
  635.     theWindow = FrontWindow();
  636.     
  637.     menu = GetMenuHandle( mFile );
  638.     
  639.     if ( theWindow )
  640.         EnableItem( menu, iClose );
  641.     else
  642.         DisableItem( menu, iClose );
  643.  
  644.     if ( GetObjectFromWindow( theWindow, &wind ) )
  645.     {
  646.         wind->AdjustMenus();
  647.     }
  648. }
  649.  
  650. //———————————————————————————————————————————————————————————————————————————
  651. //    • HandleMenuCommand
  652. //———————————————————————————————————————————————————————————————————————————
  653. //    This is called when an item is chosen from the menu bar (after calling
  654. //    MenuSelect or MenuKey). It performs the right operation for each command.
  655. //    It tries to get the command ID of the menu item selected. If it can't, or
  656. //    the command is unknown, we pass it on to the front window, if any. We
  657. //    also special case the Apple menu items.
  658. //    
  659. static void
  660. HandleMenuCommand( long menuResult )
  661. {
  662.     short        menuID;
  663.     short        menuItem;
  664.     Str255        daName;
  665.     UInt32        command;
  666.     Boolean        handled;
  667.     OSErr        err;
  668.     WindowPtr    window;
  669.     
  670.     menuID = HiWrd( menuResult );
  671.     menuItem = LoWrd( menuResult );
  672.     
  673.     err = GetMenuItemCommandID( GetMenuHandle( menuID ), menuItem, &command );
  674.     
  675.     handled = false;
  676.     
  677.     if ( err || command == 0 )
  678.     {
  679.         if ( menuID == mApple )
  680.         {
  681.             GetMenuItemText( GetMenuHandle( mApple ), menuItem, daName );
  682.             OpenDeskAcc( daName );
  683.             handled = true;
  684.         }
  685.     }
  686.     else
  687.     {
  688.         handled = true;
  689.         
  690.         switch( command )
  691.         {
  692.             case kAboutSampleCmd:
  693.                 DoAboutBox();
  694.                 break;
  695.             
  696.             case kCloseCmd:
  697.                 if ( FrontWindow() )
  698.                     CloseAnyWindow( FrontWindow() );
  699.                 break;
  700.             
  701.             case kQuitCmd:
  702.                 gQuit = true;
  703.                 break;
  704.  
  705.             case kOpenFinderWindowCmd:
  706.                 new FinderWindow();
  707.                 break;
  708.                 
  709.             case kOpenDialogWindowCmd:
  710.                 new DialogWindow();
  711.                 break;
  712.             
  713.             case kOpenBevelDialogCmd:
  714.                 new BevelDialog();
  715.                 break;
  716.             
  717.             case kBevelImageAPICmd:
  718.                 new BevelImageAPIWindow();
  719.                 break;
  720.                 
  721.             case kCDEFTesterCmd:
  722.                 new CDEFTester();
  723.                 break;
  724.             
  725.             case kStandardAlertCmd:
  726.                 TestStandardAlert();
  727.                 break;
  728.             
  729.             case kLiveFeedbackCmd:
  730.                 new LiveFeedbackDialog();
  731.                 break;
  732.             
  733.             case kUtilityWindowCmd:
  734.                 new UtilityWindow();
  735.                 break;
  736.             
  737.             case kSideUtilityWindowCmd:
  738.                 new SideUtilityWindow();
  739.                 break;
  740.             
  741.             case kMegaDialogCmd:
  742.                 new MegaDialog();
  743.                 break;
  744.             
  745.             case kAutoSizeCmd:
  746.                 AutoSizeDialogTest();
  747.                 break;
  748.             
  749.             case kVerticalZoomCmd:
  750.                 window = GetNewWindow( 133, nil, (WindowPtr)-1L );
  751.                 if ( window )
  752.                 {
  753.                     ((WindowPeek)window)->windowKind = kVertZoomKind;
  754.                     SetWindowPic( window, GetPicture( 133 ) );
  755.                     SyncVertZoomRects( window );
  756.                 }
  757.                 break;
  758.             
  759.             case kHorizontalZoomCmd:
  760.                 window = GetNewWindow( 134, nil, (WindowPtr)-1L );
  761.                 if ( window )
  762.                 {
  763.                     ((WindowPeek)window)->windowKind = kHorizZoomKind;
  764.                     SetWindowPic( window, GetPicture( 134 ) );
  765.                     SyncHorizZoomRects( window );
  766.                 }
  767.                 break;
  768.             
  769.             case kMenuDrawingTest:
  770.                 DrawMenuStuff();
  771.                 break;
  772.             
  773.             case kDumpHierarchy:
  774.                 if ( FrontWindow() )
  775.                 {
  776.                     FSSpec        file;
  777.                     
  778.                     GetReportFileSpec( &file );
  779.                     DumpControlHierarchy( FrontWindow(), &file );
  780.                 }
  781.                 break;
  782.             
  783.             default:
  784.                 handled = false;
  785.                 break;
  786.                     
  787.         }
  788.     }
  789.     
  790.     if ( !handled )
  791.     {
  792.         WindowPtr     frontWindow = FrontWindow();
  793.         BaseWindow* wind;
  794.         
  795.         if ( frontWindow )
  796.         {
  797.             if ( GetObjectFromWindow( frontWindow, &wind ) )
  798.             {
  799.                 wind->HandleMenuSelection( menuID, menuItem );
  800.             }
  801.         }
  802.     }
  803.  
  804.     HiliteMenu(0);
  805. }
  806.  
  807. //———————————————————————————————————————————————————————————————————————————
  808. //    • CloseAnyWindow
  809. //———————————————————————————————————————————————————————————————————————————
  810. //    Close the given window in a manner appropriate for that window. If the
  811. //    window belongs to a DA, we call CloseDeakAcc. For dialogs, we simply hide
  812. //    the window. If we had any document windows, we would probably call either
  813. //    DisposeWindow or CloseWindow after disposing of any document data and/or
  814. //    controls.
  815. //    
  816. static void
  817. CloseAnyWindow( WindowPtr window )
  818. {
  819.     BaseWindow*        wind;
  820.     
  821.     if ( IsDAWindow( window ) )
  822.     {
  823.         CloseDeskAcc( ((WindowPeek)window)->windowKind );
  824.     }
  825.     else if ( GetObjectFromWindow( window, &wind ) )
  826.     {
  827.         delete wind;
  828.     }
  829.     else
  830.         DisposeWindow( window );
  831. }
  832.  
  833. //———————————————————————————————————————————————————————————————————————————
  834. //    • DeathAlert
  835. //———————————————————————————————————————————————————————————————————————————
  836. //    Display an alert that tell the user an err occurred, then exit the
  837. //    program. This routine is used as an ultimate bail-out for serious errors
  838. //    that prohibit the continuation of the application. The error number is
  839. //    used to index an 'STR#' resource so that a relevant message can be
  840. //    displayed.
  841. //
  842. static void
  843. DeathAlert( short errNumber )
  844. {
  845.     short            itemHit;
  846.     Str255            theMessage;
  847.     
  848.     SetCursor( &qd.arrow );
  849.     GetIndString( theMessage, kErrorStrings, errNumber );
  850.     ParamText( theMessage, nil, nil, nil );
  851.     itemHit = StopAlert( kAlertStartupError, nil );
  852.     ExitToShell();
  853. }
  854.  
  855. //———————————————————————————————————————————————————————————————————————————
  856. //    • IsAppWindow
  857. //———————————————————————————————————————————————————————————————————————————
  858. //    Check to see if a window belongs to the application. If the window
  859. //    pointer passed was NIL, then it could not be an application window.
  860. //    WindowKinds that are negative belong to the system and windowKinds
  861. //    less that userKind are reserved by Apple except for userKinds equal to
  862. //    dialogKind, which means it's a dialog.
  863. //    
  864.  
  865. static Boolean
  866. IsAppWindow( WindowPtr window )
  867. {
  868.     short        windowKind;
  869.     
  870.     if ( window == nil )
  871.         return false;
  872.         
  873.     windowKind = ((WindowPeek)window)->windowKind;
  874.     return( (windowKind >= userKind) || (windowKind == dialogKind) );
  875. }
  876.  
  877. //———————————————————————————————————————————————————————————————————————————
  878. //    • IsDAWindow
  879. //———————————————————————————————————————————————————————————————————————————
  880. //    Check to see if a window belongs to a desk accessory. It belongs to a DA
  881. //    if the windowKind field of the window record is negative.
  882. //    
  883. static Boolean
  884. IsDAWindow( WindowPtr window )
  885. {
  886.     if ( window == nil )
  887.         return false;
  888.  
  889.     return( ((WindowPeek)window)->windowKind < 0 );
  890. }
  891.  
  892. //———————————————————————————————————————————————————————————————————————————
  893. //    • IsDialogWindow
  894. //———————————————————————————————————————————————————————————————————————————
  895. //    Check to see if a window is a dialog window. We can determine this by
  896. //    checking to see if the windowKind field is equal to dialogKind.
  897. //
  898. static Boolean
  899. IsDialogWindow( WindowPtr window )
  900. {
  901.     if ( window == nil )
  902.         return false;
  903.  
  904.     return( ((WindowPeek)window)->windowKind == dialogKind );
  905. }
  906.  
  907. //———————————————————————————————————————————————————————————————————————————
  908. //    • GetObjectFromWindow
  909. //———————————————————————————————————————————————————————————————————————————
  910. //    Gets the object pointer from the refCon of the given window if the kind
  911. //    is right. If the kind is wrong, or the refCon is null, we return false.
  912. //
  913. static Boolean
  914. GetObjectFromWindow( WindowPtr window, BaseWindow** wind )
  915. {
  916.     SInt32        test;
  917.     
  918.     if ( ((WindowPeek)window)->windowKind != kObjectWindowKind )
  919.         return false;
  920.         
  921.     test = GetWRefCon( window );
  922.     if ( test == nil ) return false;
  923.     
  924.     *wind = (BaseWindow*)test;
  925.  
  926.     return true;
  927. }
  928.  
  929. //———————————————————————————————————————————————————————————————————————————
  930. //    • SetUpFontMenu
  931. //———————————————————————————————————————————————————————————————————————————
  932. //    This routine calls AddResMenu to add all fonts to our font menu. We then
  933. //    go thru each item and set the item's font to the actual font!
  934. //
  935. static void
  936. SetUpFontMenu()
  937. {
  938.     SInt16            i, numItems;
  939.     Str255            fontName;
  940.     SInt16            fontNum;
  941.     
  942.     gFontMenu = GetMenu( kMenuFonts );
  943.     if ( gFontMenu == nil ) return;
  944.     
  945.     AppendResMenu( gFontMenu, 'FONT' );
  946.     
  947.     numItems = CountMItems( gFontMenu );
  948.     for ( i = 1; i <= numItems; i++ )
  949.     {
  950.         GetMenuItemText( gFontMenu, i, fontName );
  951.         GetFNum( fontName, &fontNum );
  952.         SetMenuItemFontID( gFontMenu, i, fontNum );
  953.     }    
  954.     InsertMenu(gFontMenu,0);
  955.     DisableItem(gFontMenu,0);
  956. }
  957.  
  958. //———————————————————————————————————————————————————————————————————————————
  959. //    • SetUpModifiersMenu
  960. //———————————————————————————————————————————————————————————————————————————
  961. //    This routine programmatically sets the modifiers for our modifier menu.
  962. //
  963. static void
  964. SetUpModifiersMenu()
  965. {
  966.     MenuHandle        menu;
  967.     Handle            suite;
  968.     OSErr            err;
  969.     
  970.     menu = GetMenuHandle( kMenuModifiers );
  971.     if ( menu == nil ) return;
  972.  
  973.     SetMenuItemModifiers( menu, kShiftModifierItem, kMenuShiftModifier );    
  974.     SetMenuItemModifiers( menu, kShiftOptionModifierItem, kMenuShiftModifier + kMenuOptionModifier );    
  975.     SetMenuItemModifiers( menu, kShiftOptCntlModifierItem, kMenuShiftModifier + kMenuOptionModifier + kMenuControlModifier );    
  976.  
  977.     SetItemCmd( menu, kCommandDeleteItem, 0x08 ); // delete key
  978.     SetMenuItemKeyGlyph( menu, kCommandDeleteItem, 0x0A ); // delete key glyph in font
  979.     
  980.     err = GetIconSuite( &suite, -3997, kSelectorAllAvailableData );
  981.     if ( err == noErr )
  982.         SetMenuItemIconHandle( menu, kIconSuiteItem, kMenuIconSuiteType, suite );
  983. }
  984.  
  985. //———————————————————————————————————————————————————————————————————————————
  986. //    • DoAboutBox
  987. //———————————————————————————————————————————————————————————————————————————
  988. //    Puts up our about box dialog. Note that we use a dialog and NOT an alert.
  989. //    This is a good practice to get into, since alerts are now colored differently
  990. //    to distiguish them from normal dialogs.
  991. //
  992. static void
  993. DoAboutBox()
  994. {
  995.     DialogPtr        dialog;
  996.     SInt16            itemHit;
  997.     
  998.     dialog = GetNewDialog( kAboutBoxDialogID, nil, (WindowPtr)-1L );
  999.     if ( dialog == nil ) return;
  1000.  
  1001.     AutoSizeDialog(dialog); 
  1002.     SetDialogDefaultItem( dialog, 4 );    
  1003.     ModalDialog( nil, &itemHit );
  1004.     
  1005.     DisposeDialog( dialog );
  1006. }
  1007.  
  1008. //————————————————————————————————————————————————————————————————————————————
  1009. //    • AutoSizeDialogTest
  1010. //————————————————————————————————————————————————————————————————————————————
  1011. //    Simple little routine to demonstrate the AutoSizeDialog API
  1012. //
  1013. static void
  1014. AutoSizeDialogTest()
  1015. {
  1016.     DialogPtr        dialog;
  1017.     SInt16            itemHit = 0;
  1018.     
  1019.     dialog = GetNewDialog( 4000, nil, (WindowPtr)-1L );
  1020.     if ( dialog == nil ) return;
  1021.     
  1022.     SetDialogDefaultItem( dialog, 2 );
  1023.     
  1024.     while ( itemHit != 2 )
  1025.     {
  1026.         ModalDialog( nil, &itemHit );
  1027.         
  1028.         if ( itemHit == 3 )
  1029.             AutoSizeDialog( dialog );
  1030.     }
  1031.     DisposeDialog( dialog );
  1032. }
  1033.  
  1034. //————————————————————————————————————————————————————————————————————————————
  1035. //    • SyncVertZoomRects
  1036. //————————————————————————————————————————————————————————————————————————————
  1037. //    Sets up the standard and user rectangles for our vertical zooming window.
  1038. //
  1039. static void
  1040. SyncVertZoomRects( WindowPtr window )
  1041. {
  1042.     Rect        bounds;
  1043.     
  1044.     SetPort( window );
  1045.     bounds = window->portRect;
  1046.     
  1047.     if ( (bounds.bottom - bounds.top) < 200 )
  1048.         bounds.bottom = bounds.top + 200;
  1049.         
  1050.     LocalToGlobal( &topLeft( bounds ) );
  1051.     LocalToGlobal( &botRight( bounds ) );
  1052.     
  1053.     SetWindowStandardState( window, &bounds );
  1054.     
  1055.     bounds.bottom = bounds.top + 60;
  1056.     SetWindowUserState( window, &bounds );
  1057. }
  1058.  
  1059. //————————————————————————————————————————————————————————————————————————————
  1060. //    • SyncHorizZoomRects
  1061. //————————————————————————————————————————————————————————————————————————————
  1062. //    Sets up the standard and user rectangles for our horizontal zooming window.
  1063. //
  1064. static void
  1065. SyncHorizZoomRects( WindowPtr window )
  1066. {
  1067.     Rect        bounds;
  1068.     
  1069.     SetPort( window );
  1070.     bounds = window->portRect;
  1071.  
  1072.     if ( (bounds.right - bounds.left) < 240 )
  1073.         bounds.right = bounds.left + 240;
  1074.         
  1075.     LocalToGlobal( &topLeft( bounds ) );
  1076.     LocalToGlobal( &botRight( bounds ) );
  1077.     
  1078.     SetWindowStandardState( window, &bounds );
  1079.     
  1080.     bounds.right = bounds.left + 60;
  1081.     SetWindowUserState( window, &bounds );
  1082. }
  1083.  
  1084. //————————————————————————————————————————————————————————————————————————————
  1085. //    • GetReportFileSpec
  1086. //————————————————————————————————————————————————————————————————————————————
  1087. //    Returns our file spec for dumping pane information.
  1088. //
  1089. static OSErr
  1090. GetReportFileSpec( FSSpecPtr file )
  1091. {
  1092.     FCBPBRec    pb;
  1093.     Str255        ourName;
  1094.     OSErr        err;
  1095.     
  1096.     pb.ioVRefNum    = -1;
  1097.     pb.ioFCBIndx    = 0;
  1098.     pb.ioNamePtr    = ourName;
  1099.     pb.ioRefNum        = CurResFile();
  1100.     
  1101.     err = PBGetFCBInfoSync( &pb );
  1102.     if ( err ) return err;
  1103.     
  1104.     err = FSMakeFSSpec( pb.ioFCBVRefNum, pb.ioFCBParID, "\pPane Dump", file );
  1105.     return err;
  1106. }
  1107.